package com.fvision.camera.view.customview;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.fvision.camera.R;
import com.fvision.camera.utils.FloatCalculator;
import com.fvision.camera.utils.LogUtils;
import com.fvision.camera.utils.SharedPreferencesUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class SVDrawRectangle extends SurfaceView implements SurfaceHolder.Callback {

    public static final int MSG_DRAW = 0x01;
    public static final int MSG_SETCHECK = 0x02;
    public static final int MSG_LANE = 0x03;
    private int m_stg_cnt = 0;
    private SurfaceHolder sh;
    private int mWidth;
    private int mHeight;
    private int offsetX = 80;// TODO
    private int offsetY = 45; // TODOoff
    int startdistance = 25;
//    private float taupaintX = 1280.f/800.f;
//    private float taupaintY = 720.f/450.f;
//    private int xCenter = 1280/2;

    private float taupaintX;
    private float taupaintY;
    private int xCenter;

    private DrawHandler mHandler;
    private final Object mLock = new Object();

    private Paint p;
    private Paint p_text;
    private Paint mBitmapPaint;

    private int mBtnLeft;
    private int mBtnTop;
    private int mBtnRight;
    private int mBtnBottom;

    private float mStartX;
    private float mStartY;

    private boolean lock = false;

    private static volatile Rect mLandRect;
    private static volatile Rect mPortRect;

    private static volatile boolean mIsDraw = true;
    private volatile float sConfigX;
    private volatile float sConfigY;

    private float countX = -1;
    private float countY = -1;

    private boolean isLand = false;
    private boolean isPort = false;

    private float maxLeft;
    private float maxTop;
    private float maxRight;
    private float maxBottom;
//    private DrawThread mDrawThread;

    private Paint mBtnPaint;
    private Rect mTextRect;
    private Bitmap mLine;
    private Matrix mPocilyMatrix;
    private int mLdwCount;
    private float[] src;
    private float[] dst;
    private boolean mLdwFlag;
    private float offX;
    private float offY;
    private Path mPath;
    private int mScanIndex;

    private Bitmap bmpLane1;
    private Bitmap bmpLane2;
    private Bitmap bmpLane3;
    private Bitmap bmpLane4;

    private List bits = null;
    private int currentBit = 1;

    private HandlerThread mDrawThread;

//    private MainActivity.IAdasConfigListener mListener;

    private boolean isWarning = false;
    private int warningCount = 100;
//    public void setListener(MainActivity.IAdasConfigListener listener) {
//        this.mListener = listener;
//    }

    public SVDrawRectangle(Context context, AttributeSet attrs) {
        super(context, attrs);
        sh = getHolder();
        sh.addCallback(this);
//        sh.setFormat(PixelFormat.TRANSPARENT);
//        setZOrderOnTop(true);
    }

    public void surfaceChanged(SurfaceHolder arg0, int arg1, int w, int h) {
        mWidth = w;
        mHeight = h;
        if (mListener != null) {
            mListener.surfaceChanged();
        }
//        sConfigX = mWidth/2;
//        sConfigY = mHeight/2;

        taupaintX = w / 800.f;
        taupaintY = h / 450.f;
        xCenter = w / 2;

        mBtnLeft = w / 2 - h / 10;
        mBtnTop = 10;
        mBtnRight = w / 2 + h / 10;
        mBtnBottom = h / 10;

        maxLeft = w / 3;
        maxTop = h / 2 - h / 8;
        maxRight = w - w / 3;
        maxBottom = h / 2 + h / 6;

        offX = (640 + offsetX) * taupaintX;
        offY = (360 + offsetY) * taupaintY;

        if (bmpLane1 == null) {
            bmpLane1 = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_adas_chedao_dh_1);
        }

        if (bmpLane2 == null) {
            bmpLane2 = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_adas_chedao_dh_2);
        }

        if (bmpLane3 == null) {
            bmpLane3 = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_adas_chedao_dh_3);
        }

        if (bmpLane4 == null) {
            bmpLane4 = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_adas_chedao_dh_4);
        }

        bits = new ArrayList();
        bits.add(bmpLane1);
        bits.add(bmpLane2);
        bits.add(bmpLane3);
        bits.add(bmpLane4);
    }

    public void surfaceCreated(SurfaceHolder arg0) {
        sh = getHolder();
        sh.addCallback(this);
//        sh.setFormat(PixelFormat.TRANSPARENT);
//        setZOrderOnTop(true);
//        mIsDraw = true;
        p = new Paint();
        p_text = new Paint();
        p_text.setAntiAlias(true);
        p_text.setStrokeWidth(3);
        p_text.setTextAlign(Paint.Align.CENTER);
        mTextRect = new Rect();
        mBtnPaint = new Paint();
        mBtnPaint.setStyle(Style.FILL);
        mBtnPaint.setColor(Color.GREEN);
        mLandRect = new Rect();
        mPortRect = new Rect();
        mPath = new Path();
        mBitmapPaint = new Paint();
        mBitmapPaint.setAntiAlias(true);
        mBitmapPaint.setFilterBitmap(true);
        mBitmapPaint.setDither(true);
        mDrawThread = new HandlerThread("SVDrawThread");
        mDrawThread.start();
        mHandler = new DrawHandler(mDrawThread.getLooper());
        mHandler.sendEmptyMessage(MSG_LANE);
        mLdwCount = 0;
        mScanIndex = 0;

        mLdwFlag = false;
        mPocilyMatrix = new Matrix();

    }

    public void surfaceDestroyed(SurfaceHolder arg0) {
        LogUtils.d("adas draw surfaceDestroyed");
        if (mHandler != null) {
            mHandler.removeMessages(MSG_DRAW);
            mHandler.removeMessages(MSG_SETCHECK);
            if (Build.VERSION.SDK_INT >= 18) {
                mDrawThread.quitSafely();
            }
            mDrawThread = null;
            mHandler = null;
        }
        mIsDraw = false;
        if (mLine != null && !mLine.isRecycled()) {
            mLine.recycle();
            mLine = null;
        }
        if (bmpLane1 != null) {
            if (!bmpLane1.isRecycled()) {
                bmpLane1.recycle();
                bmpLane1 = null;
            }
        }

        if (bmpLane2 != null) {
            if (!bmpLane2.isRecycled()) {
                bmpLane2.recycle();
                bmpLane2 = null;
            }
        }

        if (bmpLane3 != null) {
            if (!bmpLane3.isRecycled()) {
                bmpLane3.recycle();
                bmpLane3 = null;
            }
        }

        if (bmpLane4 != null) {
            if (!bmpLane4.isRecycled()) {
                bmpLane4.recycle();
                bmpLane4 = null;
            }
        }
    }

    public void setsConfigX(float sConfigX) {
        this.sConfigX = sConfigX;
    }

    public void setsConfigY(float sConfigY) {
        this.sConfigY = sConfigY;
    }

    public int getmWidth() {
        return mWidth;
    }

    public int getmHeight() {
        return mHeight;
    }

    private void drawLaneThread() {
        drawLane();
        mHandler.sendEmptyMessageDelayed(MSG_LANE, 20);
    }

    private void setCheckpoint() {
        Canvas canvas = sh.lockCanvas();
        if (canvas != null) {
            synchronized (sh) {
                p.setStrokeWidth(2);
                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
//                //draw check button.
//                canvas.drawRect(mBtnLeft,
//                        mBtnTop, mBtnRight, mBtnBottom, mBtnPaint);
//                mTextRect.set(mBtnLeft, mBtnTop, mBtnRight, mBtnBottom);
                Paint.FontMetrics fontMetrics = p_text.getFontMetrics();
                float top = fontMetrics.top;
                float bottom = fontMetrics.bottom;
                int baseLineY = (int) (mTextRect.centerY() - top / 2 - bottom / 2);
                p_text.setColor(Color.GREEN);
                p.setColor(Color.GREEN);
                p_text.setTextSize(60);
                // draw landspace line.
                if (sConfigX == maxLeft || sConfigX == maxRight) {
                    p.setColor(Color.argb(255, 252, 25, 25));
                } else {
                    p.setColor(Color.GREEN);
                }
                if (sConfigX == 0) {
                    sConfigX = mWidth / 2;
                }
                if (sConfigY == 0) {
                    sConfigY = mHeight / 2;
                }
                LogUtils.d("adas draw sConfigX " + sConfigX + " mHeight " + mHeight);
                canvas.drawText("请对齐车头中心", sConfigX, mHeight - 30, p_text);
                canvas.drawLine(sConfigX, 0, sConfigX, mHeight, p);
                mPortRect.set((int) sConfigX - 30, 0, (int) sConfigX + 30, mHeight);
                // draw portait line.
                if (sConfigY == maxTop || sConfigY == maxBottom) {
                    p.setColor(Color.argb(255, 252, 25, 25));
                } else {
                    p.setColor(Color.GREEN);
                }
                LogUtils.d("adas draw sConfigY " + sConfigY + " mWidth " + mWidth);
                canvas.drawLine(0, sConfigY, mWidth, sConfigY, p);
                canvas.drawText("请对齐地平线", mWidth / 5, sConfigY - 10, p_text);
                mLandRect.set(0, (int) sConfigY - 30, mWidth, (int) sConfigY + 30);
//                canvas.drawText(getResources().getString(R.string.ok), mTextRect.centerX(), baseLineY, p_text);
            }
            sh.unlockCanvasAndPost(canvas);
        }

    }

    private void drawLane() {
        if (isDraw() == false || bits == null) {
            return;
        }
        Canvas canvas = sh.lockCanvas();
        if (canvas != null) {
            synchronized (sh) {
                drawLdwLane(canvas);
//                Bitmap bitmap = (Bitmap)bits.get(currentBit - 1);
//                canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
//                canvas.drawBitmap(bitmap, sConfigX - bitmap.getWidth()/2,
//                        sConfigY + bitmap.getHeight()/2, mBitmapPaint);
//                if(currentBit >= 4){
//                    currentBit = 1;
//                }else {
//                    currentBit ++;
//                }
            }
            sh.unlockCanvasAndPost(canvas);
        }
    }

    public Handler getHandler() {
        return mHandler;
    }


    public void drawCheckLine() {
        if (mHandler != null) {
            Message message = mHandler.obtainMessage();
            message.what = MSG_SETCHECK;
            mHandler.sendMessage(message);
        }
    }

    public void setCheckpointXY() {
        LogUtils.d("adas draw 666666666666666666");
        if (mHandler != null) {
            Message message = mHandler.obtainMessage();
            message.what = 0x99;
            mHandler.sendMessage(message);
        }
    }

    public boolean isDraw() {
        return mIsDraw;
    }

    public void setIsDraw(boolean draw) {
        mIsDraw = draw;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:

//                float x = event.getX();
//                float y = event.getY();
//                if (x > mBtnLeft && x < mBtnRight && y > mBtnTop && y < mBtnBottom) {
//                    if (!mIsDraw) {
//                        sConfigX = sConfigX / taupaintX - offsetX;
//                        sConfigY = sConfigY / taupaintY - offsetY;
//                        mIsDraw = true;
//                    } else {
////						EventBus.getInstance().post("stop");
//                        mIsDraw = false;
//                    }
//                } else {
                mStartX = event.getX();
                mStartY = event.getY();

                if (mLandRect.contains((int) mStartX, (int) mStartY)) {
                    isLand = true;
                } else if (mPortRect.contains((int) mStartX, (int) mStartY)) {
                    isPort = true;
                }
                LogUtils.d("adas draw ACTION_DOWN mStartX " + mStartX + " mStartY " + mStartY + " isLand " + isLand + " isPort " + isPort);
//                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (!mIsDraw) {
                    setCheckpoint();
                    if (isLand) {
                        LogUtils.d("adas draw ACTION_MOVE isLand");
                        if (event.getY() >= maxBottom) {
                            sConfigY = maxBottom;
                        } else if (event.getY() <= maxTop) {
                            sConfigY = maxTop;
                        } else {
                            sConfigY = event.getY();
                        }
                    } else if (isPort) {
                        LogUtils.d("adas draw ACTION_MOVE isPort ");
                        if (event.getX() >= maxRight) {
                            sConfigX = maxRight;
                        } else if (event.getX() <= maxLeft) {
                            sConfigX = maxLeft;
                        } else {
                            sConfigX = event.getX();
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                LogUtils.d("adas draw ACTION_UP");
                isPort = false;
                isLand = false;
                break;
        }
        return true;
    }


    class DrawHandler extends Handler {
        public DrawHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case MSG_DRAW:

                    break;
                case MSG_SETCHECK:
                    setCheckpoint();
                    break;
                case MSG_LANE:
                    drawLaneThread();
                    break;
                case 0x99:
                    setCheckpointXY1();
                    break;
            }
        }
    }

    public void setCheckpointXY1() {
//        sConfigX = sConfigX / taupaintX - offsetX;
//        sConfigY = sConfigY / taupaintY - offsetY;
        countX = sConfigX;
        countY = sConfigY;
        if (mListener != null) {
            LogUtils.d("adas draw 存进去的原始的 x " + sConfigX + " y " + sConfigY);
//            float adasX = sConfigX/mWidth * 1280;
//            float adasY = sConfigY/mHeight * 720;
            float adasX = FloatCalculator.multiply(FloatCalculator.divide(sConfigX, mWidth), 1280);
            float adasY = FloatCalculator.multiply(FloatCalculator.divide(sConfigY, mHeight), 720);
            LogUtils.d("adas draw 存进去的转换后的 x " + adasX + " y " + adasY);
            mListener.setAdasConfigXY(adasX, adasY);
        }
    }

    private void drawLdwLane(Canvas canvas) {
        canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        if(isWarning){
            warningCount--;
            if(warningCount <= 0){
                isWarning = false;
            }
        }
        int trapezoidTopWidth = 150;
        int trapezoidBottomWidth = 300;
        int trapezoidHeigh = 130;

        int leftDownX = (int) (sConfigX - trapezoidBottomWidth / 2);
        int leftDownY = (int) (sConfigY + trapezoidTopWidth / 2);
        int leftUpX = (int) (sConfigX - trapezoidTopWidth / 2);
        int leftUpY = (int) (sConfigY - trapezoidHeigh / 2);
        int rightDownX = (int) (sConfigX + trapezoidBottomWidth / 2);
        int rightDownY = (int) (sConfigY + trapezoidTopWidth / 2);
        int rightUpX = (int) (sConfigX + trapezoidTopWidth / 2);
        int rightUpY = (int)(sConfigY - trapezoidHeigh/2);
        if (isWarning) {
            this.p.setShader(new LinearGradient((float) leftDownX, (float) leftDownY, (float) leftDownX, (float) leftUpY, Color.parseColor("#FF041B"), Color.TRANSPARENT, Shader.TileMode.CLAMP));
        } else {
            this.p.setShader(new LinearGradient((float) leftDownX, (float) leftDownY, (float) leftDownX, (float) leftUpY, Color.parseColor("#05E2FF"), Color.TRANSPARENT, Shader.TileMode.CLAMP));
        }
        mPath = new Path();
        mPath.moveTo((float) leftDownX, (float) leftDownY);
        mPath.lineTo((float) leftUpX, (float) leftUpY);
        mPath.lineTo((float) rightUpX, (float) leftUpY);
        mPath.lineTo((float) rightDownX, (float) rightDownY);
        this.p.setStyle(Style.FILL);
        canvas.drawPath(mPath, this.p);
        this.p.setShader(null);
        this.p.setStyle(Style.STROKE);

//                        this.p.setPathEffect(new DashPathEffect(new float[]{100.0f, 20.0f}, 0.0f));
        if (isWarning) {
            this.p.setColor(-609276);
            this.p.setShader(new LinearGradient((float) leftDownX, (float) leftDownY, (float) leftDownX, (float) leftUpY, Color.parseColor("#FF041B"), Color.TRANSPARENT, Shader.TileMode.CLAMP));
        } else {
            this.p.setColor(-1);
            this.p.setShader(new LinearGradient((float) leftDownX, (float) leftDownY, (float) leftDownX, (float) leftUpY, -1, 16777215, Shader.TileMode.CLAMP));
        }
        canvas.drawLine((float) leftUpX, (float) leftUpY, (float) leftDownX, (float) leftDownY, this.p);
        canvas.drawLine((float) rightUpX, (float) leftUpY, (float) rightDownX, (float) rightDownY, this.p);

        int distance = 25;
        startdistance--;
        if(startdistance == 0){
            startdistance = distance;
        }
        float maxYOffset = FloatCalculator.divide(trapezoidBottomWidth - trapezoidTopWidth,2);
        p.setStrokeWidth(5);
        for (int i = 0;leftDownY > leftUpY + distance * i +startdistance;i++){
            float yOffset = distance * i +startdistance;
            float scale = FloatCalculator.divide(yOffset,trapezoidHeigh);
            float offset =FloatCalculator.multiply(scale,maxYOffset) - 5;
            canvas.drawLine((float) leftUpX - offset, (float) leftUpY + yOffset, (float) rightUpX + offset, (float) rightUpY + yOffset, this.p);
        }

        p.setStrokeWidth(2);
        this.p.setPathEffect(null);
        this.p.setShader(null);

    }

    public void setWarning(boolean warning) {
        warningCount = 100;
        isWarning = warning;
    }

    private IAdasConfigListener mListener;

    public void setListener(IAdasConfigListener listener) {
        this.mListener = listener;
    }

    public interface IAdasConfigListener {
        void setAdasConfigXY(float x, float y);

        void surfaceChanged();
    }
}